package com.bookrecomm.service.impl;

import com.bookrecomm.dao.BookRepository;
import com.bookrecomm.dao.CommentRepository;
import com.bookrecomm.dao.UserRepository;
import com.bookrecomm.entity.Book;
import com.bookrecomm.entity.Comment;
import com.bookrecomm.entity.User;
import com.bookrecomm.service.CommentService;
import com.bookrecomm.vo.BookBriefVO;
import com.bookrecomm.vo.CommentVO;
import com.bookrecomm.vo.PageVO;
import com.bookrecomm.vo.UserBriefVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 评论服务实现类
 * 实现评论相关的业务逻辑
 */
@Service
public class CommentServiceImpl implements CommentService {

    @Autowired
    private CommentRepository commentRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private BookRepository bookRepository;

    /**
     * 根据ID查询评论
     * @param id 评论ID
     * @return 评论信息
     */
    @Override
    public CommentVO findById(Long id) {
        Comment comment = commentRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("评论不存在"));
        return convertToCommentVO(comment);
    }

    /**
     * 根据图书ID查询评论列表
     * @param bookId 图书ID
     * @param pageable 分页参数
     * @return 分页评论列表
     */
    @Override
    public PageVO<CommentVO> findByBookId(Long bookId, Pageable pageable) {
        // 检查图书是否存在
        Book book = bookRepository.findById(bookId)
                .orElseThrow(() -> new RuntimeException("图书不存在"));
        
        // 查询顶级评论（parentId为null的评论）
        Page<Comment> commentPage = commentRepository.findByBookIdAndParentIdIsNull(bookId, pageable);
        
        // 获取所有评论ID
        List<Long> commentIds = commentPage.getContent().stream()
                .map(Comment::getId)
                .collect(Collectors.toList());
        
        // 查询所有回复评论
        List<Comment> replies = commentRepository.findByParentIdIn(commentIds);
        
        // 按父评论ID分组
        Map<Long, List<Comment>> replyMap = replies.stream()
                .collect(Collectors.groupingBy(Comment::getParentId));
        
        // 转换为VO对象
        List<CommentVO> commentVOs = commentPage.getContent().stream()
                .map(comment -> {
                    CommentVO commentVO = convertToCommentVO(comment);
                    // 设置回复列表
                    List<Comment> commentReplies = replyMap.getOrDefault(comment.getId(), new ArrayList<>());
                    List<CommentVO> replyVOs = commentReplies.stream()
                            .map(this::convertToCommentVO)
                            .collect(Collectors.toList());
                    commentVO.setReplies(replyVOs);
                    return commentVO;
                })
                .collect(Collectors.toList());
        
        // 创建分页VO对象
        PageVO<CommentVO> pageVO = new PageVO<>();
        pageVO.setContent(commentVOs);
        pageVO.setTotalElements(commentPage.getTotalElements());
        pageVO.setTotalPages(commentPage.getTotalPages());
        pageVO.setSize(commentPage.getSize());
        pageVO.setNumber(commentPage.getNumber());
        
        return pageVO;
    }

    /**
     * 根据用户ID查询评论列表
     * @param userId 用户ID
     * @param pageable 分页参数
     * @return 分页评论列表
     */
    @Override
    public PageVO<CommentVO> findByUserId(Long userId, Pageable pageable) {
        // 检查用户是否存在
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        
        // 查询评论
        Page<Comment> commentPage = commentRepository.findByUserId(userId, pageable);
        
        // 转换为VO对象
        List<CommentVO> commentVOs = commentPage.getContent().stream()
                .map(this::convertToCommentVO)
                .collect(Collectors.toList());
        
        // 创建分页VO对象
        PageVO<CommentVO> pageVO = new PageVO<>();
        pageVO.setContent(commentVOs);
        pageVO.setTotalElements(commentPage.getTotalElements());
        pageVO.setTotalPages(commentPage.getTotalPages());
        pageVO.setSize(commentPage.getSize());
        pageVO.setNumber(commentPage.getNumber());
        
        return pageVO;
    }

    /**
     * 添加评论
     * @param comment 评论信息
     * @return 添加后的评论信息
     */
    @Override
    @Transactional
    public CommentVO addComment(Comment comment) {
        // 获取当前登录用户
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        
        // 检查图书是否存在
        Book book = bookRepository.findById(comment.getBookId())
                .orElseThrow(() -> new RuntimeException("图书不存在"));
        
        // 设置评论信息
        comment.setUserId(user.getId());
        comment.setParentId(null); // 顶级评论
        comment.setLikes(0);
        comment.setStatus(1); // 默认启用
        comment.setCreatedAt(LocalDateTime.now());
        comment.setUpdatedAt(LocalDateTime.now());
        
        // 保存评论
        Comment savedComment = commentRepository.save(comment);
        
        // 更新图书评分和评论数
        updateBookRatingAndCommentCount(book);
        
        return convertToCommentVO(savedComment);
    }

    /**
     * 回复评论
     * @param parentId 父评论ID
     * @param comment 评论信息
     * @return 添加后的评论信息
     */
    @Override
    @Transactional
    public CommentVO replyComment(Long parentId, Comment comment) {
        // 获取当前登录用户
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        
        // 检查父评论是否存在
        Comment parentComment = commentRepository.findById(parentId)
                .orElseThrow(() -> new RuntimeException("父评论不存在"));
        
        // 设置评论信息
        comment.setUserId(user.getId());
        comment.setBookId(parentComment.getBookId());
        comment.setParentId(parentId);
        comment.setRating(null); // 回复评论不设置评分
        comment.setLikes(0);
        comment.setStatus(1); // 默认启用
        comment.setCreatedAt(LocalDateTime.now());
        comment.setUpdatedAt(LocalDateTime.now());
        
        // 保存评论
        Comment savedComment = commentRepository.save(comment);
        
        return convertToCommentVO(savedComment);
    }

    /**
     * 更新评论
     * @param id 评论ID
     * @param commentUpdate 评论信息
     * @return 更新后的评论信息
     */
    @Override
    @Transactional
    public CommentVO updateComment(Long id, Comment commentUpdate) {
        // 获取当前登录用户
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        
        // 检查评论是否存在
        Comment comment = commentRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("评论不存在"));
        
        // 检查是否有权限修改评论
        if (!comment.getUserId().equals(user.getId()) && !user.getRoles().stream().anyMatch(role -> role.getName().equals("ROLE_ADMIN"))) {
            throw new RuntimeException("无权限修改该评论");
        }
        
        // 更新评论信息
        if (commentUpdate.getContent() != null) {
            comment.setContent(commentUpdate.getContent());
        }
        if (commentUpdate.getRating() != null && comment.getParentId() == null) {
            comment.setRating(commentUpdate.getRating());
            
            // 更新图书评分
            Book book = bookRepository.findById(comment.getBookId())
                    .orElseThrow(() -> new RuntimeException("图书不存在"));
            updateBookRatingAndCommentCount(book);
        }
        
        // 更新时间
        comment.setUpdatedAt(LocalDateTime.now());
        
        // 保存评论
        Comment savedComment = commentRepository.save(comment);
        
        return convertToCommentVO(savedComment);
    }

    /**
     * 删除评论
     * @param id 评论ID
     * @return 是否删除成功
     */
    @Override
    @Transactional
    public boolean deleteComment(Long id) {
        // 获取当前登录用户
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        
        // 检查评论是否存在
        Comment comment = commentRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("评论不存在"));
        
        // 检查是否有权限删除评论
        if (!comment.getUserId().equals(user.getId()) && !user.getRoles().stream().anyMatch(role -> role.getName().equals("ROLE_ADMIN"))) {
            throw new RuntimeException("无权限删除该评论");
        }
        
        // 如果是顶级评论，删除所有回复
        if (comment.getParentId() == null) {
            commentRepository.deleteByParentId(id);
            
            // 删除评论
            commentRepository.deleteById(id);
            
            // 更新图书评分和评论数
            Book book = bookRepository.findById(comment.getBookId())
                    .orElseThrow(() -> new RuntimeException("图书不存在"));
            updateBookRatingAndCommentCount(book);
        } else {
            // 删除回复评论
            commentRepository.deleteById(id);
        }
        
        return true;
    }

    /**
     * 点赞评论
     * @param id 评论ID
     * @param userId 用户ID
     * @return 更新后的评论信息
     */
    @Override
    @Transactional
    public CommentVO likeComment(Long id, Long userId) {
        // 检查评论是否存在
        Comment comment = commentRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("评论不存在"));
        
        // 增加点赞数
        comment.setLikes(comment.getLikes() + 1);
        
        // 更新时间
        comment.setUpdatedAt(LocalDateTime.now());
        
        // 保存评论
        Comment savedComment = commentRepository.save(comment);
        
        return convertToCommentVO(savedComment);
    }

    /**
     * 取消点赞评论
     * @param id 评论ID
     * @param userId 用户ID
     * @return 更新后的评论信息
     */
    @Override
    @Transactional
    public CommentVO unlikeComment(Long id, Long userId) {
        // 检查评论是否存在
        Comment comment = commentRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("评论不存在"));
        
        // 减少点赞数
        if (comment.getLikes() > 0) {
            comment.setLikes(comment.getLikes() - 1);
        }
        
        // 更新时间
        comment.setUpdatedAt(LocalDateTime.now());
        
        // 保存评论
        Comment savedComment = commentRepository.save(comment);
        
        return convertToCommentVO(savedComment);
    }

    /**
     * 更新图书评分和评论数
     * @param book 图书
     */
    private void updateBookRatingAndCommentCount(Book book) {
        // 查询图书的所有顶级评论
        List<Comment> comments = commentRepository.findByBookIdAndParentIdIsNullAndRatingIsNotNull(book.getId());
        
        // 计算平均评分
        BigDecimal avgRating = BigDecimal.ZERO;
        if (!comments.isEmpty()) {
            // 计算评分总和
            BigDecimal ratingSum = comments.stream()
                    .map(Comment::getRating)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            
            // 计算平均值，保留一位小数
            avgRating = ratingSum.divide(new BigDecimal(comments.size()), 1, java.math.RoundingMode.HALF_UP);
        }
        
        // 更新图书评分和评论数
        book.setRating(avgRating);
        book.setCommentCount((long) comments.size());
        book.setUpdatedAt(LocalDateTime.now());
        
        // 保存图书
        bookRepository.save(book);
    }

    /**
     * 将评论实体转换为VO对象
     * @param comment 评论实体
     * @return 评论VO对象
     */
    private CommentVO convertToCommentVO(Comment comment) {
        CommentVO commentVO = new CommentVO();
        BeanUtils.copyProperties(comment, commentVO);
        
        // 设置用户信息
        User user = userRepository.findById(comment.getUserId())
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        UserBriefVO userBriefVO = new UserBriefVO();
        userBriefVO.setId(user.getId());
        userBriefVO.setUsername(user.getUsername());
        userBriefVO.setNickname(user.getNickname());
        userBriefVO.setAvatar(user.getAvatar());
        commentVO.setUser(userBriefVO);
        
        // 设置图书信息
        Book book = bookRepository.findById(comment.getBookId())
                .orElseThrow(() -> new RuntimeException("图书不存在"));
        BookBriefVO bookBriefVO = new BookBriefVO();
        bookBriefVO.setId(book.getId());
        bookBriefVO.setTitle(book.getTitle());
        bookBriefVO.setCoverUrl(book.getCoverUrl());
        bookBriefVO.setAuthor(book.getAuthor());
        commentVO.setBook(bookBriefVO);
        
        // 初始化回复列表
        commentVO.setReplies(new ArrayList<>());
        
        return commentVO;
    }
}
